Introducción a los Sistemas Operativos
Un sistema operativo debe cumplir:
- Administrar la ejecución de programas (creación de procesos)
- Comunicación entre programas
- Ser interfaz de usuario
- Ser interfaz con los dispositivos
- Administrar la memoria
- Administrar los archivos
- Administrar los dispositivos de IO
Componentes de un sistema operativo
Un wrapper es una función de más alto nivel que las syscalls. Ejemplo de wrapper es la función malloc(), la función que nosotros llamamos para pedirle memoria al sistema está compuesta de varias syscalls que interactúan con el kernel.
La razón por la que usamos malloc por ejemplo, y no interactuamos directamente con el kernel es por un tema de seguridad.
Modos de ejecución
Las instrucciones privilegiadas son propias del modo kernel, el modo usuario no puede ejecutar instrucciones privilegiadas.
Ejemplos de instrucciones privilegiadas son: hablar entre procesos, tocar memoria directamente, deshabilitar las interrupciones, tratar interrupciones, etc.
Cambio de modo
¿Cómo sabemos cuál es el modo actual de ejecución? Mediante el PSW.
Para pasar de modo usuario a modo kernel, las formas van a ser a través de atender interrupciones o generar syscalls. De la última forma, lo que se va a hacer es cederle la ejecución al sistema operativo. Antiguamente lo que sucedía era que esa misma syscall llamaba a otra rutina (mediante una interrupción) la cual a su vez se ejecutaba, pasando así al modo kernel; en los últimos tiempos lo que se empezó a usar hasta el día de hoy son las fast syscalls, que no generan interrupciones sino que entienden las syscalls SYSENTER y SISEXIT.
Para pasar de modo kernel a modo usuario lo que se van a ejecutar son instrucciones privilegiadas, o bien se va a volver restaurando el contexto, cuando termina la rutina de X interrupción por ejemplo.
Estructura del Sistema Operativo
Existen varios diseños a la hora de implementar un S.O (multicapa, maquina virtual), los más importantes en este momento van a ser el monolítico y el microkernel, donde vamos a ver cómo se distribuyen las funcionalidades que corren en modo kernel y cuales en modo usuario.
La diferencia entre ambos, por decirlo de alguna manera, es que el diseño microkernel es más robusto, debido a que tiene menos funcionalidades a nivel kernel que el monolítico, por ende la probabilidad de que se produzcan errores fatales es mucho menor. El tema acá, es que el microkernel genera mucho overhead (pérdida innecesaria de tiempo), ya que se producen muchos cambios de modo innecesarios, debido a que muchas funcionalidades del modo usuario deben pasar primero por el modo kernel para poder ejecutarse.